/**
 * 
 */
package envios;

import static org.junit.Assert.*;
import static org.mockito.Mockito.*;

import org.junit.Before;
import org.junit.Test;
import org.joda.time.DateTime;

import clientes.Cliente;
import estadosDelEnvio.Cancelado;
import estadosDelEnvio.EnProcesoDeEnvio;
import estadosDelEnvio.Entregado;
import exceptions.StatesException;
import ventas.VentaConEnvioAPagar;
import ventas.VentaConEnvioYaPagado;

/**
 * @author Lucas Alan Silvestri.
 *
 */
public abstract class EnviosTest {
	
	private Envio sut;
	private VentaConEnvioAPagar ventaAPagar;
	private VentaConEnvioYaPagado ventaPagada ;
	private Cliente clienteDeLaVenta;
	

	/**
	 * @throws java.lang.Exception
	 */
	@Before
	public void setUp() throws Exception {
		this.setVentaAPagar(mock(VentaConEnvioAPagar.class));
		this.setVentaPagada(mock(VentaConEnvioYaPagado.class));
		this.setClienteDeLaVenta(mock(Cliente.class));
		when(this.getVentaPagada().getClienteQueDeseaRealizarLaCompra()).thenReturn(
				this.getClienteDeLaVenta());
		when(this.getVentaAPagar().getClienteQueDeseaRealizarLaCompra()).thenReturn(
				this.getClienteDeLaVenta());
		when(this.getClienteDeLaVenta().getDomicilio()).thenReturn(
				"Dr Agote 1446, Quilmes Oeste");
	}

	/**
	 * Se verifica si un envio se encuentra pendiete de envio
	 * a la hora de ser creado.
	 * @throws StatesException
	 */
	@Test
	public void verificarElEnvioSeEncuentraPendenteDeEnvio() {
		assertEquals(true, this.getSut().estaPendienteDeEnvio());
		}
	
	/**
	 * Se verifica qu un envio no se encuentra pendiete de envio.
	 * @throws StatesException
	 */
	@Test
	public void verificarElEnvioNoSeEncuentraPendenteDeEnvio() {
		this.getSut().cambiarEstado(new Entregado());
		assertEquals(false, this.getSut().estaPendienteDeEnvio());
		}
	
	/**
	 * Se verifica si el envio luego de ser enviado, se encuentra
	 * en proceso de envio.
	 * @throws StatesException
	 */
	@Test
	public void verificarSiComenzoElEnvio() throws StatesException {
		this.getSut().enviar();
		assertEquals(true, this.getSut().estaEnProcesoDeEnvio());
		}
	
	/**
	 * este test demuestra que no se puede enviar un envio
	 * ya entregado.
	 * @throws StatesException
	 */
	@Test(expected = StatesException.class)
	public void verificarSiNoComenzoElEnvio() throws StatesException {
		this.getSut().cambiarEstado(new Entregado());
		this.getSut().enviar();
		}
	
	/**
	 * este test demuestra que no se puede entregar un envio
	 * ya entregado.
	 * @throws StatesException
	 */
	@Test(expected = StatesException.class)
	public void verificarSiNoSeEntregoElEnvio() throws StatesException {
		this.getSut().cambiarEstado(new Entregado());
		this.getSut().entregar();
		}
	
	/**
	 * este test demuestra que se puede entregar un envio
	 * en proceso de envio.
	 * @throws StatesException
	 */
	@Test
	public void verificarSiSeEntregoElEnvio() throws StatesException {
		this.getSut().cambiarEstado(new EnProcesoDeEnvio());
		this.getSut().entregar();
		assertEquals(true, this.getSut().estaEntregado());
		}
	
	/**
	 * este test demuestra que no se puede entregar un envio
	 * ya entregado.
	 * @throws StatesException
	 */
	@Test(expected = StatesException.class)
	public void verificarSiNoSeCanceloElEnvio() throws StatesException {
		this.getSut().cambiarEstado(new Cancelado());
		this.getSut().cancelar();
		}
	
	/**
	 * este test demuestra que se puede entregar un envio
	 * en proceso de envio.
	 * @throws StatesException
	 */
	@Test
	public void verificarSiSeCanceloElEnvio() throws StatesException {
		this.getSut().cambiarEstado(new EnProcesoDeEnvio());
		this.getSut().cancelar();
		assertEquals(true, this.getSut().estaCancelado());
		}
	
	/**
	 * este test demuestra que en el domicilio del envio
	 * se encuentra el domicilio correcto del cliente.
	 */
	@Test
	public void domicilioCorrectoTest(){
		assertEquals("Dr Agote 1446, Quilmes Oeste",
				this.getSut().getDomicilio());
	}
	
	/**
	 * Se verifica si se reprogramo la fecha de entrega
	 * Del envio.
	 */
	@Test
	public void verificarSiSeReprogramoElEnvioApagar(){
		DateTime fechaDelEnvio = this.getSut().getFecha();
		this.getSut().reprogramar(new DateTime(2014, 12, 12, 10, 23));
		assertNotEquals(fechaDelEnvio, this.getSut().getFecha());
	}
	
	/**
	 * Dada una compra hecha, demuetra que se modifico el
	 * historial de compras la reprogramar el envio.
	 */
	@Test
	public void verificarHistorialDeFechasDeEnvioYaPagado() {
	DateTime fechaDelEnvio = this.getSut().getFecha();
	this.getSut().reprogramar(new DateTime(2014, 8, 12, 10, 23));
	this.getSut().reprogramar(new DateTime(2014, 12, 12, 10, 23));
		assertEquals(this.getSut().getHistorialDeFechas().size(), 2);
		assertEquals(this.getSut().getHistorialDeFechas().get(0),
				new DateTime(fechaDelEnvio));
		assertEquals(this.getSut().getHistorialDeFechas().get(1),
				new DateTime(2014, 8, 12, 10, 23));
		assertEquals(this.getSut().getFecha(),
				new DateTime(2014, 12, 12, 10, 23));
	}

	/**
	 * @return the sut
	 */
	public Envio getSut() {
		return sut;
	}

	/**
	 * @param sut the sut to set
	 */
	public void setSut(Envio sut) {
		this.sut = sut;
	}

	/**
	 * @return the ventaAPagar
	 */
	public VentaConEnvioAPagar getVentaAPagar() {
		return ventaAPagar;
	}

	/**
	 * @param ventaAPagar the ventaAPagar to set
	 */
	public void setVentaAPagar(VentaConEnvioAPagar ventaAPagar) {
		this.ventaAPagar = ventaAPagar;
	}

	/**
	 * @return the ventaPagada
	 */
	public VentaConEnvioYaPagado getVentaPagada() {
		return ventaPagada;
	}

	/**
	 * @param ventaPagada the ventaPagada to set
	 */
	public void setVentaPagada(VentaConEnvioYaPagado ventaPagada) {
		this.ventaPagada = ventaPagada;
	}

	/**
	 * @return the clienteDeLaVenta
	 */
	public Cliente getClienteDeLaVenta() {
		return clienteDeLaVenta;
	}

	/**
	 * @param clienteDeLaVenta the clienteDeLaVenta to set
	 */
	public void setClienteDeLaVenta(Cliente clienteDeLaVenta) {
		this.clienteDeLaVenta = clienteDeLaVenta;
	}

}
